//=============================================================================
// ProMesh.NET - .NET Web Application Framework 
//
// Copyright (c) 2003-2008 Philippe Leybaert
//
// Permission is hereby granted, free of charge, to any person obtaining a copy 
// of this software and associated documentation files (the "Software"), to deal 
// in the Software without restriction, including without limitation the rights 
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
// copies of the Software, and to permit persons to whom the Software is 
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in 
// all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//=============================================================================

using System;
using System.Diagnostics;
using System.Threading;
using System.Collections.Generic;

namespace Activa.ProMesh
{
    internal class ProMeshPageHandler
    {
        private readonly ControllerAction _controllerAction;

        internal ProMeshPageHandler(ControllerAction controllerAction)
        {
            _controllerAction = controllerAction;
        }

        public void ProcessRequest(ProMeshHttpContext httpContext)
        {
            httpContext.Handler = this;

            WebAppContext.Reset();

            Stopwatch stopWatchRun = new Stopwatch();
            Stopwatch stopWatchRender = new Stopwatch();
            Stopwatch stopWatchTotal = new Stopwatch();

            stopWatchRun.Start();
            stopWatchTotal.Start();

            View view = null;

            try
            {
                stopWatchRun.Start();

                view = WebAppHelper.RunControllerAction(_controllerAction);

                stopWatchRun.Stop();

                httpContext.Response.RenderedView = view;

                if (view != null)
                {
                    stopWatchRender.Start();

                    string pageContent = view.Render();

                    stopWatchRender.Stop();
                    stopWatchTotal.Stop();

                    if (WebAppConfig.LoggingProvider != null)
                    {
                        WebAppConfig.LoggingProvider.LogPage(WebAppContext.Session.SessionID, WebAppContext.UrlWithoutExtension, GetQueryString(),
                                                             WebAppContext.Session.LanguageCode, 
                                                             view.LayoutName, view.ViewName, 
                                                             (int) stopWatchRun.ElapsedMilliseconds,
                                                             (int) stopWatchRender.ElapsedMilliseconds,
                                                             (int) stopWatchTotal.ElapsedMilliseconds);
                    }

                    httpContext.Response.AppendHeader("X-Powered-By", "ProMesh.NET v" + WebAppConfig.Version);

                    httpContext.Response.Write(pageContent);
                }
            }

            catch (TemplateNotFoundException templateException)
            {
                if (!WebAppConfig.Fire_PageNotFound(WebAppContext.UrlWithoutExtension))
                {
                    httpContext.Response.Write(templateException.Message);
                }
            }

            catch (RedirectPageException exception)
            {
                if (WebAppConfig.LoggingProvider != null && view != null)
                {
                    WebAppConfig.LoggingProvider.LogPage(WebAppContext.Session.SessionID, WebAppContext.UrlWithoutExtension, GetQueryString(), WebAppContext.Session.LanguageCode, view.LayoutName, view.ViewName, (int)stopWatchRun.ElapsedMilliseconds, (int)stopWatchRender.ElapsedMilliseconds, (int)stopWatchTotal.ElapsedMilliseconds);
                }

                // NewUrl is null when Response.End() is called from an offline session
                if (exception.NewUrl != null)
                    ProMeshHttpContext.Current.Response.Redirect(exception.NewUrl);
            }

            catch (ThreadAbortException)
            {
                if (WebAppConfig.LoggingProvider != null && view != null)
                {
                    WebAppConfig.LoggingProvider.LogPage(WebAppContext.Session.SessionID, WebAppContext.UrlWithoutExtension, GetQueryString(), WebAppContext.Session.LanguageCode, view.LayoutName, view.ViewName, (int)stopWatchRun.ElapsedMilliseconds, (int)stopWatchRender.ElapsedMilliseconds, (int)stopWatchTotal.ElapsedMilliseconds);
                }

                throw; // Occurs when Response.End() is called, and is handled by the ASP.NET runtime
            }

            catch (Exception ex)
            {
                if (ex.InnerException is ThreadAbortException)
                    throw ex.InnerException;

                if (!WebAppConfig.Fire_ExceptionHandler(ex))
                {
                    httpContext.Response.Write("<pre>");

                    for (Exception currentException = ex; currentException != null; currentException = currentException.InnerException)
                    {
                        httpContext.Response.Write("<em><b>" + currentException.Message + "</b></em><br/>");

                        httpContext.Response.Write(currentException.StackTrace);
                        httpContext.Response.Write("<hr>");
                    }

                    httpContext.Response.Write("</pre>");
                }
            }
        }

        private static string GetQueryString()
        {
            string rawUrl = ProMeshHttpContext.Current.Request.RawUrl;

            if (rawUrl.IndexOf("?") >= 0)
                return rawUrl.Substring(rawUrl.IndexOf("?") + 1);
            else
                return "";
        }
    }

}
